import 'dart:isolate';
import 'dart:math';

import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

/// 2022年更新  适配 flutter 3.0
class IsolateHandlerMessagePage extends StatefulWidget {
  const IsolateHandlerMessagePage({super.key});

  @override
  State<StatefulWidget> createState() {
    return _IsolateHandlerMessagePageState();
  }
}

class _IsolateHandlerMessagePageState extends State<IsolateHandlerMessagePage> {
  double _sum = 0;
  int _elapsedTime = 0;
  double _currentProgress = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      floatingActionButton: FloatingActionButton(
        onPressed: _doTask,
        child: const Icon(Icons.directions_run),
      ),
      appBar: AppBar(
        title: const Text("isolate 消息通信 "),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Text("1亿随机数平均值测试"),
            Text(
              "计算结果: $_sum",
              style: Theme.of(context).textTheme.headline6,
            ),
            Text("计算总耗时: $_elapsedTime ms"),
            const SizedBox(
              height: 10,
            ),
            Row(
              children: [
                Spacer(),
                Expanded(
                  child: LinearProgressIndicator(
                    value: _currentProgress,
                  ),
                ),
                Spacer(),
              ],
            ),
            const SizedBox(
              height: 5,
            ),
            Text("当前进度: ${(_currentProgress * 100).toStringAsFixed(2)}%"),
          ],
        ),
      ),
    );
  }

  void _doTask() async {
    ///定义消息通道
    final receivePort = RawReceivePort()..handler = handleMessage;

    ///Isolate.spawn 来开启新 isolate
    ///参数一 耗时任务；参数二
    await Isolate.spawn(
      _doTaskInCompute,
      receivePort.sendPort,
      onError: receivePort.sendPort,
      onExit: receivePort.sendPort,
    );
  }

  void handleMessage(dynamic msg) {
    debugPrint("消息 $msg");
    if (msg is AsyncResultInfo) {
      _currentProgress = 1;
      _sum = msg.sum;
      _elapsedTime = msg.elapsedTime;
      setState(() {});
    } else if (msg is double) {
      setState(() {
        _currentProgress = msg;
      });
    }
  }

  static Random random = Random();

  static void _doTaskInCompute(SendPort sendPort) async {
    //计算次数
    int count = 1000 * 1000 * 1000;
    //计算结果
    double sum = 0;
    //开始的时间
    int startTime = DateTime.now().millisecondsSinceEpoch;
    for (int i = 0; i < count; i++) {
      //每次相加 100
      sum += random.nextInt(100);
      //每100000次里发送一次消息
      if (i % 100000 == 0) {
        sendPort.send(i / count);
      }
    }
    //结束的时间
    int endTime = DateTime.now().millisecondsSinceEpoch;
    //耗时
    int elapsedTime = endTime - startTime;
    //结束 返回结果
    Isolate.exit(sendPort, AsyncResultInfo(sum: sum, elapsedTime: elapsedTime));
  }
}

class AsyncResultInfo {
  final int elapsedTime;
  final double sum;

  AsyncResultInfo({required this.elapsedTime, required this.sum});
}
